package com.allwees.bs.c.module.order.controller;

import com.alibaba.fastjson.JSON;
import com.allwees.bs.c.module.base.controller.BaseController;
import com.allwees.bs.c.module.order.constant.EOrderQueryType;
import com.allwees.bs.c.module.order.dto.OrderDTO;
import com.allwees.bs.c.module.order.dto.OrderItemDTO;
import com.allwees.bs.c.module.order.dto.TrackingDetailDTO;
import com.allwees.bs.c.module.order.req.OrderApplyRefundReq;
import com.allwees.bs.c.module.order.req.OrderCancelReq;
import com.allwees.bs.c.module.order.req.OrderCreateReq;
import com.allwees.bs.c.module.order.req.OrderReviewReq;
import com.allwees.bs.c.module.order.service.IOrderCreateService;
import com.allwees.bs.c.module.order.service.IOrderItemService;
import com.allwees.bs.c.module.order.service.IOrderRefundService;
import com.allwees.bs.c.module.order.service.IOrderService;
import com.allwees.bs.core.modelbase.page.PageParams;
import com.allwees.bs.core.modelbase.vo.R;
import com.allwees.core.common.util.http.RequestContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**
 * 订单相关
 */
@Slf4j
@RestController
public class OrderController extends BaseController {
    @Autowired
    private IOrderService orderService;

    @Autowired
    private IOrderItemService orderItemService;

    @Autowired
    private IOrderCreateService orderCreateService;

    @Autowired
    private IOrderRefundService orderRefundService;

    // ******************************************* 订单基本操作 *******************************************

//    /**
//     * 使用优惠券
//     *
//     * @param req 优惠数据
//     * @return 订单信息
//     */
//    @PostMapping("/api/v1/orders/use-coupon")
//    @ApiOperation(value = "使用优惠券", response = CartDTO.class)
//    public R useCoupon(@RequestBody CartCheckoutReq req) {
//        CartDTO dto = this.orderCreateService.calculateOrder(req);
//        return R.ok( dto);
//    }
//
//    /**
//     * checkout
//     *
//     * @return 订单信息
//     */
//    @PostMapping("/api/v1/orders/checkout")
//    @ApiOperation(value = "使用优惠券", response = CartDTO.class)
//    public R checkout(@RequestBody CartCheckoutReq req) {
//        CartDTO dto = this.orderCreateService.calculateOrder(req);
//        return R.ok(dto);
//    }

    /**
     * 校验库存和新手礼
     *
     * @param createReq
     * @return
     */
    @PostMapping("/api/v1/user/checkOrder")
    public R checkOrders(@RequestBody @Validated OrderCreateReq createReq, HttpServletRequest request) {
        createReq.setPlatform(RequestContext.getPlatform());
        createReq.setCheckOrder(true);
        this.orderCreateService.createOrder(getUserUuid(), createReq, RequestContext.getChannel());
        return R.ok(true);
    }


    /**
     * 对商品进行下单
     *
     * @param createReq 下单数据
     * @return 订单信息
     */
    @PostMapping("/api/v1/user/orders")
    public R placeOrder(@RequestBody @Validated OrderCreateReq createReq, HttpServletRequest request) {
        log.info("========placeOrder接口参数:{}", JSON.toJSONString(createReq));
        createReq.setPlatform(RequestContext.getPlatform());
        // 同步下单
        createReq.setCheckOrder(false);
        OrderDTO order = this.orderCreateService.createOrder(getUserUuid(), createReq, RequestContext.getChannel());
        log.info("========placeOrder接口返回:{}", JSON.toJSONString(order));
        return R.ok(order);
    }

    /**
     * 模拟支付成功回调
     *
     * @param orderUuid 下单数据
     * @return 订单信息
     */
    @GetMapping("/api/v1/orders/mock-order-pay")
    public R mockPayOrder(@RequestParam(value = "orderUuid") String orderUuid) {
        return R.ok(this.orderService.payOrder(orderUuid, null, null));
    }

    /**
     * 获取个人订单列表，可根据订单状态筛选
     * 标准翻页
     *
     * @param queryType 查询类型
     * @return 订单列表信息
     */
    @GetMapping("/api/v1/user/orders")
    public R getUserOrderList(
            @RequestParam(required = false) EOrderQueryType queryType,
            @RequestParam(required = false) Integer type, PageParams pageParams) {
        return R.ok(this.orderService.fetchUserOrders(getUserUuid(), queryType, type, pageParams));
    }

    /**
     * 根据order_item_uuid获取订单的物流详情
     *
     * @param orderItemUuid
     * @return 物流详情Json
     */
    @GetMapping("/api/v1/orders/tracking-detail/{order_item_uuid}")
    public R queryTrackingDetail(@PathVariable("order_item_uuid") String orderItemUuid) {
        TrackingDetailDTO dto = orderService.queryTrackingDetail(getUserUuid(), orderItemUuid);
        return R.ok(dto);
    }


    /**
     * 用户确认收货
     *
     * @param orderItemUuid 订单ID
     * @return 订单详情
     */
    @PostMapping("/api/v1/user/orders/{orderItemUuid}/confirmShipping")
    public R confirmShippingOrder(@PathVariable("orderItemUuid") String orderItemUuid) {
        OrderDTO orderDTO = this.orderService.userConfirmShippingOrder(getUserUuid(), orderItemUuid);
        return R.ok(orderDTO);
    }

    /**
     * 获取订单详情
     *
     * @param orderUuid 订单ID
     * @return 订单详情数据
     */
    @GetMapping("/api/v1/user/orders/{orderUuid}")
    public R getOrder(@PathVariable("orderUuid") String orderUuid) {
        OrderDTO orderDTO = this.orderService.fetchUserOrder(getUserUuid(), orderUuid);
        return R.ok(orderDTO);
    }

    /**
     * 对某个订单项进行评价
     *
     * @param orderReviewReq
     * @return
     */

    /*
    @ApiOperation(value = "对订单项进行评价")
    @ApiResponses({@ApiResponse(code = 1001, message = "订单未成功"),
            @ApiResponse(code = 1002, message = "当前时间无法评价"),
            @ApiResponse(code = 1003, message = "只能评价自己的订单项"),
            @ApiResponse(code = 1004, message = "已经评价")})*/
    @PostMapping("/api/v1/user/orderitem/review")
    public R reviewOrderItem(@Validated @RequestBody OrderReviewReq orderReviewReq) {
        orderService.reviewOrderItem(getUserUuid(), orderReviewReq);
        return R.ok();
    }

    /**
     * 订单明细详情
     *
     * @param orderUuid 订单ID
     * @return 订单详情数据
     */
    @GetMapping("/api/v1/user/orders/{orderUuid}/{orderItemUuid}")
    public R getOrder(@PathVariable("orderUuid") String orderUuid, @PathVariable("orderItemUuid") String orderItemUuid) {
        OrderItemDTO orderItem = this.orderService.findOrderItem(getUserUuid(), orderUuid, orderItemUuid);
        return R.ok(orderItem);
    }

    /**
     * 取消订单(支付前)
     *
     * @param orderUuid 订单ID
     * @param req       订单需要原因，备注等信息
     * @return 订单信息
     */
    @PostMapping("/api/v1/user/orders/{orderUuid}/cancel")
    public R cancelOrder(@PathVariable("orderUuid") String orderUuid, @Validated @RequestBody OrderCancelReq req) {
        OrderDTO dto = orderService.userCancelOrder(getUserUuid(), orderUuid, req);
        return R.ok(dto);
    }

    /**
     * 用户申请退款
     *
     * @param orderUuid 订单ID
     * @param req       退款原因等信息
     * @return 订单详情
     */
    @PostMapping("/api/v1/user/orders/{orderUuid}/refund")
    public R refundOrder(@PathVariable("orderUuid") String orderUuid, @Validated @RequestBody OrderApplyRefundReq req) {
        /**
         * 在内部去设置 refundChannelUuid 会涉及的改动特别大，故在用户审请时提前设置。
         */
        String channel = RequestContext.getChannel();
        orderItemService.updateRefundChannelUuidByOrderItemUuid(req.getOrderItemUuid(), channel);
        orderService.updateRefundChannelIdByOrderUuid(orderUuid, channel);

        OrderDTO dto = orderItemService.userRequestRefundOrder(getUserUuid(), orderUuid, req);
        return R.ok(dto);
    }

    /**
     * 撤销订单申请退款
     *
     * @param orderRefundUuid 订单ID
     * @return 订单详情
     */
    @DeleteMapping("/api/v1/user/orders/{orderRefundUuid}/refund")
    public R cancelRefundOrder(@PathVariable String orderRefundUuid) {
        this.orderRefundService.cancel(getUserUuid(), orderRefundUuid);
        return R.ok();
    }


    // ******************************************* 订单活动相关 *******************************************

    /**
     * 获取直播订单
     *
     * @param productUuid
     * @return
     */
    @GetMapping("/api/v1/orders/live")
    public R getLiveOrder(
            @RequestParam(required = false, value = "productUuid")
                    String productUuid) {
        return R.ok(this.orderService.fetchLiveOrder(productUuid));
    }

//    /**
//     * 获取订单快照
//     *
//     * @param orderUuid 订单ID
//     * @return 订单快照数据
//     */
//    @GetMapping("/api/v1/user/ordersnap/{orderUuid}")
//    @ApiOperation(value = "获取订单快照", response = OrderDTO.class)
//    public ResultData getOrderSnap(@PathVariable("orderUuid") @ApiParam(name = "orderUuid", value = "订单ID") String orderUuid) {
//        OrderSnapEntity snapEntity = orderSnapService.getOrderSnap(new Specification<OrderSnapEntity>() {
//            @Override
//            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder cb) {
//                Path<String> exp1 = root.get("prodName");
//                Path<String> exp2 = root.get("quantity");
//                Path<String> exp3 = root.get("orderUuid");
//                // Demo1
//                //这里可以设置任意条查询条件
////                criteriaQuery.where(cb.like(exp1, "%%"), cb.like(exp2, "%%"));
//                //这种方式使用JPA的API设置了查询条件，所以不需要再返回查询条件Predicate给Spring Data Jpa，故最后return null;即可。
////                return null;
//                // Demo2
////                Predicate predicate = cb.and(cb.like(exp1, "%taskName%"),cb.lessThan(exp2, ""));
////                return cb.or(predicate,cb.equal(exp3, orderUuid));
//                criteriaQuery.where(cb.equal(exp3, orderUuid));
//                return null;
//            }
//        });
//        OrderSnapDTO snapDTO = new OrderSnapDTO(snapEntity);
//        return R.ok("get order snapshot success", snapDTO);
//    }
}
